import config
import requests
from concurrent.futures import ThreadPoolExecutor
import time
import sqlite3
from threading import Lock
import flask
from dataclasses import dataclass
import ujson
import base64
from datetime import timedelta
pool = ThreadPoolExecutor(10)
client = requests.session()
client.proxies = config.PROXY
offset = 0

conn = sqlite3.connect("data.db", check_same_thread=False)
lock = Lock()
app = flask.Flask("jiangyan")
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = timedelta(seconds=1)


@dataclass
class JiangYan:
    id: int
    text: str
    image: bytes
    comment: str
    upload_time: int


def make_url(url: str):
    return f"https://api.telegram.org/bot{config.TOKEN}/{url}"


@app.route("/get", methods=["POST", "GET"])
@app.route("/get/<int:id>", methods=["POST", "GET"])
def route_get_jiangyan(id: int = None):
    result = get_from_database(id)
    _dict = result.__dict__
    _dict["image"] = base64.encodebytes(
        result.image).decode().replace("\n", "")
    return ujson.dumps(_dict)


@app.route("/photo", methods=["POST", "GET"])
@app.route("/photo/<int:id>", methods=["POST", "GET"])
def route_get_jiangyan_photo(id: int = None):
    result = get_from_database(id)
    from io import BytesIO
    buf = BytesIO()
    buf.write(result.image)
    buf.seek(0)
    return flask.send_file(buf, mimetype="image/png")


def get_from_database(id: int = None):
    with lock:
        if not id:
            import random
            ids = [x[0]
                   for x in conn.execute("SELECT ID FROM JIANGYAN").fetchall()] or [-1]
            id = random.choice(ids)
        selected = conn.execute(
            "SELECT UPLOAD_TIME,IMAGE,TEXT,COMMENT FROM JIANGYAN WHERE ID = ?", [id]).fetchone()

        if not selected:
            flask.abort(404)
        return JiangYan(
            id, selected[2], selected[1], selected[3], selected[0]
        )


def store_into_database(text: str, image: bytes, timestamp: int, comment="", message_id=-1):
    lock.acquire()
    cursor = conn.cursor()
    cursor.execute("INSERT INTO JIANGYAN (UPLOAD_TIME,IMAGE,TEXT,COMMENT,MESSAGE_ID) VALUES (?,?,?,?,?)", [
                   timestamp, image, text, comment, message_id])
    last_id = cursor.execute(
        "select last_insert_rowid() FROM JIANGYAN").fetchone()[0]
    print(f"{last_id} {message_id} saved.")
    conn.commit()
    lock.release()


def download_photo(file_id: str, caption: str, timestamp: int, comment="", message_id: int = -1):
    file_obj = requests.post(make_url("getFile"), params={
        "file_id": file_id}).json()["result"]
    print("Downloading photo...", file_obj)
    with client.get(f"https://api.telegram.org/file/bot{config.TOKEN}/{file_obj['file_path']}", proxies=config.PROXY) as resp:
        print(resp.request.url)
        image = resp.content
    store_into_database(caption, image, timestamp, comment, message_id)


def main():
    while True:
        print("Fetching updates...")
        global offset
        try:
            with requests.post(make_url("getUpdates"), proxies=config.PROXY, params={"offset": offset}) as resp:
                result = resp.json()["result"]
                offset = max([item["update_id"] for item in result]+[0])+1
                print(result)
                for message in result:
                    if "channel_post" in message and message["channel_post"]["chat"]["username"] == config.CHANNEL:
                        post = message["channel_post"]
                        if "photo" in message["channel_post"]:
                            # print(file)
                            pool.submit(download_photo,
                                        message["channel_post"]["photo"][-1]["file_id"],
                                        message["channel_post"].get(
                                            "caption", ""),
                                        message["channel_post"]["date"],
                                        "",
                                        post["message_id"]
                                        ).add_done_callback(exception_handler)
                        elif "text" in message["channel_post"]:
                            store_into_database(
                                message["channel_post"]["text"], b"", message["channel_post"]["date"], "", post["message_id"])
                        elif "document" in message["channel_post"]:
                            pool.submit(download_photo, post["document"]["file_id"], "", post["date"], "", post["message_id"]).add_done_callback(
                                exception_handler)
                        elif "sticker" in message["channel_post"]:
                            pool.submit(download_photo, post["sticker"]["file_id"], "", post["date"], "", post["message_id"]).add_done_callback(
                                exception_handler)
                            # [{'update_id': 544906186, 'channel_post': {'message_id': 55, 'chat': {'id': -1001489572805, 'title': '姜言收集', 'username': 'jiang_yan', 'type': 'channel'}, 'date': 1585028017, 'sticker': {'width': 512, 'height': 122, 'emoji': '�', 'set_name': 'onionSoStrong', 'is_animated': False, 'thumb': {'file_id': 'AAMCBQADHQJYyRPFAAM3XnmbsVUcMKmx2EB04bZkYYD0R-sAAigAA5fKmCIXeojNVYQ_7khSgGp0AAMBAAdtAAN_WQACGAQ', 'file_unique_id': 'AQADSFKAanQAA39ZAAI', 'file_size': 2778, 'width': 320, 'height': 76}, 'file_id': 'CAACAgUAAx0CWMkTxQADN155m7FVHDCpsdhAdOG2ZGGA9EfrAAIoAAOXypgiF3qIzVWEP-4YBA', 'file_unique_id': 'AgADKAADl8qYIg', 'file_size': 5848}}}]
        except:
            import traceback
            traceback.print_exc()


def exception_handler(future):
    if future.exception():
        raise future.exception()


@app.before_first_request
def init():
    pool.submit(main).add_done_callback(exception_handler)
